<?php

namespace Fund\Points;

use app\api\model\User;
use app\api\model\UserPoints;
use app\api\model\UserPointsLog;
use think\facade\Db;

abstract class Fund
{

    /**
     * 业务类型
     * @var
     */
    protected $business_type;

    /**
     * 备注
     * @var string
     */
    protected $remark = "";

    /**
     * 变动金额
     * @var int
     */
    protected $money = 0;

    /**
     * 额外参数
     * @var array
     */
    protected $params = [];

    /**
     * 用户信息
     * @var int|User
     */
    protected $user;

    /**
     * 交易方向
     * @var
     */
    protected $direct = "";

    /**
     * 是否记录日志
     * @var bool
     */
    protected $recordLog = true;

    /**
     * @var bool
     */
    protected $targetId = 0;

    /**
     * 修改金额
     * @param UserPoints $userPoints
     * @param String $direct
     * @return array
     */
    abstract public function _change(User $user, string $direct): array;

    /**
     * 设置业务类型
     */
    abstract public function setBusinessType();

    /**
     * 设置备注
     */
    public function setRemark()
    {
        if (!$this->remark) {
            $this->remark = UserPointsLog::getTypesInfo()[$this->business_type] ?? '';
        }
    }

    /**
     * @throws \Exception
     */
    protected function modify()
    {
        //初始化数据
        $this->init();
        //处理用户信息
        $this->user();
        //校验参数
        $this->checkData();
        //变动金额
        $info = $this->change();
        if ($this->recordLog) {
            //增加日志
            $this->addLog($info['before'], $info['after']);
            $this->addWalletLog($info['before'], $info['after']);
        }
    }

    /**
     * 增加日志
     * @param $before
     * @param $after
     */
    public function addWalletLog($before, $after)
    {
       Db::name("member_wallet_log")->insert([
            'uid' => $this->user->id,
            'before_price' => $before['balance'],
            'after_price' => $after['balance'],
            'type' => 2,
            'brief' => $this->remark,
            'amount' => $this->money,
            'change' => $this->direct,
            'category' => 1,
            'create_time' => time(),
        ]);
    }

    public function addLog($before, $after)
    {
        UserPointsLog::create([
            'user_id'        => $this->user->id,
            'before_amount'  => $before['balance'],
            'after_amount'   => $after['balance'],
            'remark'         => $this->remark,
            'amount'         => $this->money,
            'business_type'  => $this->business_type,
            'direction'      => $this->direct,
            'target_id'      => $this->targetId,
        ]);
    }



    /**
     * 变动金额
     * @throws \Exception
     */
    public function change(): array
    {
        $user = $this->user;
//        if (!$userPoints) {
//            $userPoints = UserPoints::create(['user_id' => $this->user->id]);
//        }

        if (!$user) {
            throw new \Exception("账户信息不存在");
        }

        $wallet = Db::name("user_wallet")->where("user_id",$user->id)->where("type",1)->find();
        if ($this->direct == UserPointsLog::DIRECT_SUB && $wallet['amount'] < $this->money) {
            throw new \Exception("余额不足");
        }

        if ($this->direct == UserPointsLog::DIRECT_ADD) {
            $direct = "+";
        } else if ($this->direct == UserPointsLog::DIRECT_SUB) {
            $direct = "-";
        } else {
            throw new \Exception("无交易方向");
        }

        $data = $this->_change($user, $direct);

        return $data;
    }

    /**
     * 校验参数
     * @throws \Exception
     */
    public function checkData()
    {
        if ($this->recordLog) {
            if (!$this->business_type) {
                throw new \Exception("请指定业务类型");
            }
            if (!in_array($this->business_type, UserPointsLog::getTypes())) {
                throw new \Exception("无效的业务类型");
            }
        }
        if (!$this->money) {
            throw new \Exception("请指定数量");
        }
        if ($this->money < 0) {
            throw new \Exception("数量不能为负值");
        }
    }

    /**
     * 处理用户信息
     * @throws \Exception
     */
    public function user()
    {
        if (!$this->user) {
            throw new \Exception("请指定用户");
        }
        if (!($this->user instanceof User)) {
            $this->user = User::find($this->user);
            if (!$this->user) {
                throw new \Exception("用户不存在");
            }
        }
    }

    /**
     * 数据初始化
     */
    public function init()
    {
        $this->setBusinessType();
        $this->setRemark();
    }
}
